/*
 * Created by Spear (http://www.codernet.es), spear@codernet.es
 * Coordinator of XNA Community (http://www.codeplex.com/XNACommunity)
 * 
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using System.ComponentModel;
using XMas;

namespace XMasContent
{
    [ContentProcessor(DisplayName = "XMAS - Cald3DProcess")]
    public class CCald3DProcess : ModelProcessor
    {
        #region Fields

        CSkeletonData  skeleton_data;
        string         directory;        
        private bool   bIncludeShader = true;
        private string modelTextureName;

        #endregion


        #region Properties

        [DisplayName("Model Texture")]
        [Description("This file is texture model datal.")]
        [DefaultValue("")]
        [Browsable(true)]
        public string ModelTextureName
        {
            get { return modelTextureName; }
            set { modelTextureName = value; }
        }        

        [DisplayName("Include shader and texture")]
        [Description("Set to true if you can include shader and texture into model automatly.")]
        [DefaultValue(true)]
        [Browsable(true)]
        public bool IncludeShader
        {
            get { return bIncludeShader; }
            set { bIncludeShader = value; }
        }

        #endregion


        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();
            XmasContent.GetInstance().SetContextProcessor(context);
            skeleton_data = new CSkeletonData();            
            if (input == null)
                throw new ArgumentNullException("input");

            // Load material
            directory = Path.GetDirectoryName(input.Identity.SourceFilename);
            if (bIncludeShader)
                loadTextureModel(input);

            //Bind skeleton
            BoneContent bind_skeleton = MeshHelper.FindSkeleton(input);
            ModelContent model = base.Process(input, context);            
            XmasContent.GetInstance().warn("\n\nBind skeleton:", false);
            IList<BoneContent> bind_bones = MeshHelper.FlattenSkeleton(bind_skeleton);
            foreach (BoneContent bone in bind_bones)
            {
                skeleton_data.bind_skeleton.Add(bone.Transform);
                skeleton_data.inverse_bind_skeleton.Add(Matrix.Invert(bone.AbsoluteTransform));
            }

            // Cal3D models are rotated
            skeleton_data.worldModelTransform = Matrix.CreateFromYawPitchRoll(0, (float)Math.PI / -2.0f, 0);


            // Load anims
            string[] anim_files = Directory.GetFiles(directory, "*.caf");
            for (int i = 0; i < anim_files.Length; ++i)
            {
                CCal3DAnimParser anim_parser = new CCal3DAnimParser();
                anim_parser.load(anim_files[i], context, skeleton_data, bind_skeleton);
            }            

            model.Tag = skeleton_data;
            return model;
        }

        private void loadTextureModel(NodeContent node)
        {
            MeshContent mesh = node as MeshContent;
            if (mesh != null)
            {
                // If we need to find texture name
                string texture_filename = "";
                if (ModelTextureName == null || ModelTextureName.Length == 0)
                {
                    string[] texture_files = Directory.GetFiles(directory, "*.tga");//jpg|*.tga|*.bmp");
                    if (texture_files.Length > 0)
                        texture_filename = Path.GetFullPath(Path.Combine(directory, texture_files[0]));
                    else
                    {
                        texture_files = Directory.GetFiles(directory, "*.jpg");
                        if (texture_files.Length > 0)
                            texture_filename = Path.GetFullPath(Path.Combine(directory, texture_files[0]));
                        else
                        {
                            texture_files = Directory.GetFiles(directory, "*.bmp");
                            if (texture_files.Length > 0)
                                texture_filename = Path.GetFullPath(Path.Combine(directory, texture_files[0]));
                        }
                    }
                }
                else
                    texture_filename = Path.GetFullPath(Path.Combine(directory, ModelTextureName));

                if (texture_filename != "" && File.Exists(texture_filename))
                {
                    foreach (GeometryContent geometry in mesh.Geometry)
                    {
                        geometry.Material.Textures.Add("Texture",
                            new ExternalReference<TextureContent>(texture_filename));
                    }
                }
            }
            foreach (NodeContent child in node.Children)
            {
                loadTextureModel(child);
            }
        }
    

        protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
        {
            if (!bIncludeShader)
                return base.ConvertMaterial(material, context);

            return XmasContent.GetInstance().GetSkinningMaterial(directory, material, context);
        }
    }
}
